
#include "libBigNum.h"
unsigned short  precision=ACCURANCY;

/*function for seting precision of calculation*/
bool setDivisionPrecision(unsigned short x)
{
	if(x>0)
	 {
		 precision=x;
		 return true;
	}
	else 
	   return false;
}

big_number big_number::operator /(const big_number &param) const
{
   big_number temp;
   if(param==0)
	   throw BNException(ZERO_DEVISION_ERR);
   if(param!=0)
      temp=DIVISION(*this,param); 
   else
   {
	   exit(0);
   }
   return temp;
  }



big_number big_number:: DIVISION (const big_number &x,const big_number &y)const
  {
    big_number quotinent,accur,num_5("5.0"),temp;
	int i=0;           
	unsigned long long temp_a=0;
	long double temp_c,temp_d;
	int decimal;
	bool frac_flag=true;
	unsigned short accur_up;
	accur_up=x._arr_size-x._fractionalPart+precision;
    decimal=y._arr_size-y._fractionalPart-2;
    temp_a=y._num_array[i];
	while (temp_a==0&&i<y._arr_size)
	{
		i++;
		decimal--;
		temp_a=temp_a*1000000000+y._num_array[i];//the loop is required for a numbers from the range: 1 and -1 
	}
 	if(++i<y._arr_size)
	  temp_a=temp_a*1000000000+y._num_array[i];
	else decimal++;
	temp_c=(long double)1/(long double)temp_a; // x(0)
	
	while(temp_c<1 )
	{
	  temp_c*=1000000000;
	  decimal++;
	}
	
	free(temp._num_array);
	if(y._num_array[0]!= 0)//num>=1
	  {
		  temp._arr_size=accur_up*2+2; //ACCURANCY (decimal-1);
	   
	  }
	else
	{
		temp._arr_size=accur_up*2+(-decimal)+2;
	}
    temp._fractionalPart=accur_up*2+1;    //for more accurance calculations
	temp._num_array=(unsigned long*) calloc(temp._arr_size,sizeof(unsigned long)); 
	for(i=0,temp_d=temp_c;i<=(-decimal);i++)
		{
		  temp._num_array[i]=(unsigned long)temp_d;
		  temp_d=(temp_d-(long double)((unsigned long)temp_d))*1000000000;
	    }
	for ( i = 0,temp_d=temp_c; i < decimal; i++)
		{
          temp._num_array[i]=0;			
		}
	for(;i<temp._arr_size;i++)
	    {
		  temp._num_array[i]=(unsigned long)temp_d;
		  temp_d=(temp_d-(long double)((unsigned long)temp_d))*1000000000;	
	    }
	for(i=temp._arr_size-1;i>temp._arr_size-temp._fractionalPart;i--)
	{
		if(temp._num_array[i]==0&& frac_flag)
		  {
		     temp._fractionalPart--;
			 temp._arr_size--;
		  }
		else
		    frac_flag=false;		
	}
	if(temp._num_array[0]==0&&(temp._arr_size-temp._fractionalPart)>1)
		temp._arr_size--;

	temp._sign=y._sign;
	free(accur._num_array);
	accur._num_array=(unsigned long*)calloc((accur_up+1),sizeof(unsigned long));
	accur._num_array[accur_up]=1;
	accur._arr_size=accur_up+1;
	accur._fractionalPart=accur_up; //0.0000...01 (num of zeroes after dot= ACCURANCE)
	accur._sign=true;                //needed known 'positive' for absolute value comparison
	quotinent=temp;
	do        //interaction loop for x(n+1)-x(n)
	{
		if(quotinent._fractionalPart>3*accur_up+1)
		  {
			  quotinent._arr_size=quotinent._arr_size-quotinent._fractionalPart+3*accur_up;
		      quotinent._fractionalPart=3*accur_up;
		  }
		temp=quotinent;
		quotinent=temp*(2-y*temp);
        quotinent=(quotinent+temp)*big_number("0.5");
	} while(ABS(quotinent-temp)>accur);
	free(num_5._num_array);
	num_5._num_array=(unsigned long*)calloc((precision+2),sizeof(unsigned long));
	num_5._num_array[precision+1]=500000000;
	num_5._arr_size=precision+2;
	num_5._fractionalPart=precision+1; //0.0000...01 (num of zeroes after dot= ACCURANCE)
	num_5._sign=true;                  //needed known 'positive' for absolute value comparison


	quotinent=x*quotinent;
	if(quotinent._sign)                  // rounding
	   quotinent+=num_5;
	else
       quotinent-=num_5;
	quotinent._arr_size-=(quotinent._fractionalPart-precision);
	quotinent._fractionalPart=precision;
	quotinent._sign=(x._sign==y._sign);	
	return quotinent;	   
 }
